Skip to content

feat: add FormRequest for encapsulating validation and authorization#10087

Open
michalsn wants to merge 3 commits intocodeigniter4:4.8from
michalsn:feat/form-request
Open

feat: add FormRequest for encapsulating validation and authorization#10087
michalsn wants to merge 3 commits intocodeigniter4:4.8from
michalsn:feat/form-request

Conversation

@michalsn
Copy link
Copy Markdown
Member

@michalsn michalsn commented Apr 6, 2026

Description
This PR introduces FormRequest, an abstract base class that lets you move validation rules, custom error messages, and authorization logic out of controller methods and into a dedicated class. You type-hint the class in the controller signature, and the framework resolves, authorizes, and validates the request automatically before the method body runs.

A make:request spark command scaffolds new classes. Injection works in both controller methods and closure routes, with route parameters resolved positionally alongside the FormRequest.

I'd like your opinions on whether this belongs in the framework. Personally, I find it useful - once an app grows, controllers tend to fill up with validation boilerplate. FormRequest moves that out, keeps controllers focused on the "happy path", and makes the rules reusable across endpoints.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@michalsn michalsn added new feature PRs for new features 4.8 PRs that target the `4.8` branch. labels Apr 6, 2026
Copy link
Copy Markdown
Member

@paulbalandan paulbalandan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the same named class in Laravel useful before for focused request validation. If the functionality is similar to that, then I think it would be also beneficial here.

Some initial thoughts:

* so their callable signatures cannot be expressed precisely in PHPDoc.
*
* @param string $from The route path (with placeholders or regex)
* @param array|Closure|string $to The route handler
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about Closure(mixed...): mixed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPStan would complain. A route closure that type-hints a FormRequest parameter doesn't match Closure(mixed...). This is a regression compared to what we had in PHPDocs... but I'm not sure if we can do something about it. Any suggestions are welcome.

@patel-vansh
Copy link
Copy Markdown
Contributor

Overall, this is a really nice feature to have. Most of the times, I have to create a final class which has static functions which return array of validation rules and call Validation service in controller. But looks like I have easier way to do that from 4.8.0.

Thanks @michalsn

@neznaika0
Copy link
Copy Markdown
Contributor

You've started developing magic (autowire). It would be great not to limit yourself to one form and continue the idea. set the Autowire interface and any available class can be connected as in other frameworks.

I think it can be done a long time ago. But the framework adheres to the rules from the 2000s =) Less obscure magic. Thus, we come to the need for DI/ServiceLocator, which is now replacing Services.

You can view https://github.com/PHP-DI/PHP-DI as a separate package.

@neznaika0
Copy link
Copy Markdown
Contributor

I'm already making a similar object for validation myself, only directly PostService::fromRequest(PostShema::rules())

Co-authored-by: John Paul E. Balandan, CPA <paulbalandan@gmail.com>
@michalsn
Copy link
Copy Markdown
Member Author

michalsn commented Apr 6, 2026

@paulbalandan I took the idea for this directly from Laravel.

@michalsn
Copy link
Copy Markdown
Member Author

michalsn commented Apr 6, 2026

@neznaika0 Thanks for the feedback. FormRequest injection is intentionally narrow - it resolves one specific type at one specific point, not a general autowiring mechanism. Extending it into full container autowiring would go against CodeIgniter core philosophy of keeping things explicit and easy to follow. One of CI4 strengths is that you can trace exactly what's happening without implicit magic - and a general DI container trades that away.

Full DI container support is a legitimate feature in frameworks that prioritize that approach, but I don't believe it's the direction CI4 is going. That's not a weakness - it's more a positioning decision.

@neznaika0
Copy link
Copy Markdown
Contributor

That's the philosophy I'm talking about.

I'm worried that subsequent similar improvements will use the same principle, but duplicate the logic. Right now, I can't say what would be useful to dynamically add to the controllers.. Everything is possible - Models, Services, Configs.. in the end, we come to DI =).

I think that's why many people don't look towards CI, because they're used to magic SF, Laravel. Wordpress is an exception - it has a large community and allows non-standard approaches.

@michalsn
Copy link
Copy Markdown
Member Author

michalsn commented Apr 6, 2026

I'm worried that subsequent similar improvements will use the same principle, but duplicate the logic. Right now, I can't say what would be useful to dynamically add to the controllers.. Everything is possible - Models, Services, Configs.. in the end, we come to DI =).

That's a real concern. FormRequest is a one-off - it solves a specific problem with a clear boundary. I don't plan to allow similar injections without a broader design discussion first.

In fact Services are CodeIgniter answer to dependency management - explicit, overridable, and testable. They're not a DI container in the classical sense, but they serve the same purpose without the implicit magic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.8 PRs that target the `4.8` branch. new feature PRs for new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants